package com.itheima.ai.controller;


import com.itheima.ai.entity.vo.Result;
import com.itheima.ai.repository.ChatHistoryRepository;
import com.itheima.ai.repository.FileRepository;
import com.itheima.ai.repository.LocalPDFFileRepository;
import com.itheima.ai.tools.VectorTools;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

@RequiredArgsConstructor
@RestController
@RequestMapping("/ai/pdf")
@Slf4j
public class pdfController {


    private final FileRepository localPDFFileRepository;

    private final VectorTools vectorTools;

    private final ChatClient pdfChatClient;

    private final ChatHistoryRepository chatHistoryRepository;

    /**
     * 获取上传的文件，并将文件保存到本地，并写入向量数据库
     * @param chatId
     * @param file
     * @return
     */
    @RequestMapping(value = "/upload/{chatId}",produces = "application/json")
    public Result uploadPdf(@PathVariable("chatId") String chatId, @RequestParam("file") MultipartFile file) {
        try {
            //检查是否为PDF格式
            if (!Objects.equals(file.getContentType(), "application/pdf")) {
                return Result.fail("错误！只能上传PDF文件！");
            }
            //保存文件
            boolean save = localPDFFileRepository.save(chatId, file.getResource());
            if (!save) {
                return Result.fail("保存文件失败");
            }
            //写入向量数据库
            vectorTools.WritePDFtoVectorDatabase(file.getResource());
            return Result.ok();
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }
    @RequestMapping("/file/{chatId}")
    public ResponseEntity<Resource> getFile(@PathVariable("chatId") String chatId) {
        //读取文件，并判断是否存在
        Resource file = localPDFFileRepository.getFile(chatId);
        if (!file.exists()) {
            return ResponseEntity.notFound().build();
        }
        //文件名编码，写入响应头
        String fileName = URLEncoder.encode(Objects.requireNonNull(file.getFilename()), StandardCharsets.UTF_8);
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
                .body(file);
    }

    @RequestMapping(value = "/chat",produces = "text/html;charset=utf-8")
    public Flux<String> chat(String chatId, String prompt){
        Resource file = localPDFFileRepository.getFile(chatId);
        if (!file.exists() ) {
            throw new RuntimeException("会话文件不存在！");
        }
        chatHistoryRepository.save("pdf", chatId);
        return pdfChatClient.prompt()
                .user(prompt)
                .advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId))
                .advisors(advisorSpec -> advisorSpec.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "file_name == '"+file.getFilename()+"'"))
                .stream()
                .content();
    }
}
